<template lang="pug">
  StepPage.w-100(
    v-if="stepInfoList.length"
    ref="stepPage"
    :hasFooter="false"
    :stepList="stepInfoList"
    :actIndex="stepActIndex"
    @stepper-finished="getStepFinish")
    .step-content(
      :key="curSlotName"
      :slot="curSlotName")
      .info
        .row
          .number 工单号：{{allFormValues.orderCode}}
        .row
          .col-md-10
            ImportantInfo.important-info(
              :infoList="initFlowList"
              :formValues="allFormValues.formValues"
              :columns="infoColumns")
          .col-md-2.status-box
            //- button.btn(:class="showStep?'btn-success':'btn-complete'" @click="showStep = !showStep") {{showStep? '关闭 流程图' : '查看 流程图'}}
            p.status 状态
            .status-name(v-if="isGetRelation") {{allFormValues.status | infoRender(statusOptions)}}
          .col-md-12
            el-collapse.flow-important-info(v-model="activeName")
              el-collapse-item(
                v-for="(item, index) in importantInfoList"
                :key="index"
                :name="item.stepDefineId")
                template(slot="title")
                  .base-title
                    .weight 【{{item.stepDefineName}}】
                    div
                      span.weight 操作人：
                      span {{item.operatorName}}
                      small.col-warning(v-if="item.isAgentOperator && item.assignedUserId === curUser") (代理，原处理人：{{item.operatorName}})
                    div
                      span.weight 操作时间：
                      span {{item.updateTime | formatTime($moment)}}
                ImportantInfo(
                  v-if="item.infoList.length"
                  :infoList="item.infoList"
                  :formValues="item.infoValues"
                  :columns="infoColumns")
      .form-list-wrap
        .smart-form-box(v-for="(item, index) in formLists")
          h4.title-label {{item.name}}
            small.col-warning.small-text(v-if="curStepInsList[item.id].isAgentOperator && curStepInsList[item.id].assignedUserId === curUser") （代理，原处理人：{{curStepInsList[item.id].operatorName}}）
          .smart-form-wrap
            SmartForm.form-box(
              :formList="item.formList"
              :columns="item.formColumns"
              :values="item.formValues"
              :buttonList="item.formButtons")
      .subForm-content.col-12.m-b-20
        SubFormStep(
          ref="subFormStep"
          v-if="subformList.length"
          v-model="subFormDatas"
          :subForms="subformList"
          :subDatas="subFormDatas"
          :full="subColumns"
          :curInstance="curStepInsList"
          @create="createSubForm"
          @delete="deleteSubForm"
          @update="updateSubForm")
        .info(v-if="!formLists.length")
          .number 无表单信息
      //- 查看流程图
      SmartDialog(
        v-if="showStep"
        v-model="showStep"
        title="查看流程图"
        size="full")
        FlowDiagram(
          v-if="showStep"
          :stepDatas="stepInfoList"
          :transDatas="flowTransList"
          :active="curStepInsList")
      //- 弹框选择操作人
    SmartDialog(
      v-if="dialogVisible"
      v-model="dialogVisible"
      title="指定下一步操作人"
      size="md")
      SmartForm.smart-form-dialogwrap(
        labelPosition="right"
        :labelSize="4"
        :formList="dialogFormList"
        :values="dialogFormValues"
        :columns="dialogColumns"
        :buttonList="dialogButtonList"
        :formEnterIndex="0")
</template>

<script>
// uniq,
import { keyBy, isArray } from 'lodash'
import StepPage from '@/components/Step/StepPage'
import SmartDialog from '@/components/SmartDialog'
// import ImportantInfo from '@/components/ImportantInfo'
import ImportantInfo from '@/components/ImportantInfo'
import SmartForm from '@/components/SmartForm'
// import InfoRender from '@/components/InfoRender'
import {renderForm, getDyncRelation, renderFormByArray, renderValuesForForm, filterInstanceByStatus} from './renderForm'
import {getUserId} from '@/utils/auth'

import {columns as defaultFlowColumns} from '../../config/workFlow'
// import {testTransfer} from './testData'
import FlowDiagram from './FlowDiagram'
import SubFormStep from './SubFormStep'

export default {
  name: 'FlowStep',
  components: {
    StepPage,
    ImportantInfo,
    SmartForm,
    SmartDialog,
    SubFormStep,
    FlowDiagram
    // InfoRender
  },
  created () {
    this.getFlowDetail()
    this.getRelation()
  },
  filters: {
    formatTime (time, moment) {
      return moment(time).format('YYYY-MM-DD HH:mm:ss')
    },
    infoRender (val, options) {
      const option = options.find(option => option.value === val)
      return option ? option.label : ''
    }
  },
  route: {
    canActivate (transition) {
      transition.next()
    }
  },
  data () {
    return {
      subformList: [], // 子表关键字段
      subFormDatas: {}, // 子表数据
      subColumns: {}, // 所有子表配置
      activeName: '0',
      statusOptions: [],
      curUser: Number(getUserId()), // 当前用户
      flowInstanceId: this.$route.query.flow,
      inline: true,
      isGetRelation: false,
      curStepInsList: [], // 当前活动实例
      allFormValues: {}, // 整体流程数据
      stepTransferList: [], // 流转，full
      stepDefineList: [], // 流程定义，full
      stepInstanceList: [], // 流程实例列表，full
      startNode: {}, // 开始节点
      /* 表单字段 */
      formLists: [],
      formColumns: {},
      formValues: {},
      curFormValues: {},
      formButtonList: [],
      /* 步骤条信息 */
      stepActIndex: 0,
      stepInfoList: [],
      slotName: '',
      showStep: false,
      flowTransList: [],
      /* 重要信息 */
      initFlowList: ['applyOrgName', 'applyUserName', 'applyTime', 'createTime', 'updateTime'],
      importantInfoList: [],
      infoValues: {},
      infoColumns: {},
      /* 弹框数据 */
      dialogVisible: false,
      dialogFormList: [],
      dialogColumns: {},
      // dialogButtonList: [],
      dialogButtonList: [{
        label: '发起工单',
        type: 'complete',
        validate: true,
        func: ({funcProps}) => {
          const {form, button} = funcProps
          const {formValues} = form
          const stepDefines = renderValuesForForm(formValues)
          this.postWorkFlow(this.formValues, formValues.transType, stepDefines, button)
        }
      }],
      dialogFormValues: {}
    }
  },
  watch: {
    formColumns (val) {
      if (!val) {
        this.$set(this, 'formButonList', [{
          label: '没有需要处理的工单，点击返回',
          func: () => {
            this.$router.go(-1)
          }
        }])
      }
    }
  },
  computed: {
    curSlotName: {
      get () {
        return this.stepInfoList[this.stepActIndex].name
      },
      set (value) {
        this.slotName = value
      }
    }
  },
  methods: {
    /* stepPage 关闭 */
    getStepFinish (val) {
      // this.beforeCloseDialog()
    },
    /* 重置数据 */
    resetDatas () {
      const curIndex = this.stepActIndex = 0
      this.curSlotName = this.stepInfoList[curIndex].name
    },
    /* 获取节点信息 */
    getFlowDetail () {
      this.$get({
        url: `/workflow/flowInstance/${this.flowInstanceId}`
      }).then(res => {
        if (!res) return
        const {
          id,
          stepDefineList, // 当前定义节点列表
          stepTransferList,
          stepInstanceList, // 实例节点列表
          formValues, // 当前节点最新数据
          columns,
          formFields // 所有字段columns
        } = res
        this.allFormValues = res
        this.stepDefineList = stepDefineList
        this.stepInstanceList = stepInstanceList
        this.flowTransList = stepTransferList
        // 当前实例列表
        // 获取当前活动实例节点，需要根据3个条件筛查出节点定义id - 兼容分支的情况
        const {stepIds} = this.returnCurInstanceList(res)
        // 开始节点
        this.startNode = stepDefineList.filter(list => list.stepTypeId === 'START')
        // n个定义节点列表
        const curDefineList = this.returnCurDefineList(stepIds, stepDefineList)
        // console.log('curDefineList-', curDefineList)
        this.stepTransferList = this.renderTransferPath(stepTransferList)
        // 表单信息
        this.formLists = this.renderFormList(curDefineList, stepIds)
        // step
        this.renderStepDatas(stepInstanceList, stepDefineList, stepIds)
        // 重要信息
        const {importantInfoList, infoColumns, infoValues} = this.renderImportantInfo({stepInstanceList, flowValues: formValues, flowColumns: columns})
        this.importantInfoList = importantInfoList
        this.infoColumns = infoColumns
        this.infoValues = infoValues
        /* 获取子表字段，及数据 */
        // 获取有子表的实例，子表字段，有子表的定义节点为了拿实例...
        this.subformList = this.filterSubFormInstance(stepInstanceList, formFields.columns)
        // console.log('this.subformList:', this.subformList)
        // 从多个实例中获取子表数据
        this.subformList.map(sub => {
          this.getSubForm(sub.name, sub.subFormId, id)
        })
      })
    },
    /**
     * @desc 返回n个当前操作者实例节点列表, 实例节点id列表， 定义节点id列表
     * @return {iList: []} 当前活动节点对象数组
     * @return {stepIds: []} 所有当前活动节点id数组
    */
    returnCurInstanceList (res) {
      const {stepInstanceList: instance, status: flowStatus} = res
      const actNodeList = flowStatus === 'ACTIVATY' ? instance.filter(ins => {
        const {operatorId, status, stepNature, assignedUserId} = ins
        return status === 'ACTIVATY' && (operatorId === this.curUser || assignedUserId === this.curUser) && stepNature === 'BIZ'
      }) : []
      // console.log('actNodeList-', actNodeList)
      const stepIds = keyBy(actNodeList.map(list => {
        return {
          prevStepDefineId: list.prevStepDefineId,
          prevStepInstanceId: list.prevStepInstanceId,
          curStepDefineId: list.stepDefineId,
          curStepInstanceId: list.id
        }
      }), 'curStepDefineId')
      this.curStepInsList = keyBy(actNodeList, 'stepDefineId')
      return {
        iList: actNodeList, // 当前活动节点对象数组
        stepIds: stepIds // 所有当前活动节点id数组
      }
    },
    /**
     * @return {[]} n个定义节点列表
     */
    returnCurDefineList (nodes = [], dLists = []) {
      const dNodeIds = Object.keys(nodes)
      return dNodeIds.map(node => {
        return keyBy(dLists, 'id')[Number(node)]
      })
    },
    /**
     * @return  返回n个当前用户活动实例的表单定义信息
     * */
    renderFormList (dList, stepIds) {
      return dList.map(list => {
        const {formList, formColumns, formValues} = renderForm(list.formFields)
        const {columns} = getDyncRelation({target: this, columns: formColumns})
        const hadReset = this.hadResetStep(list.id) // 是否有回退节点
        let _newResetsVal = {}
        if (hadReset) {
          hadReset.formValues.map(item => { _newResetsVal[item.name] = item.formValue })
        } else {
          _newResetsVal = formValues
        }
        return {
          ...list,
          id: list.id,
          formList: formList.filter(key => {
            return columns[key].dataType !== 'subform'
          }),
          formColumns: columns,
          formValues: {
            ..._newResetsVal,
            ...stepIds[list.id]
          },
          formButtons: this.renderFormButtons(list.formButtons)
          // formButtons: formButtons
        }
      })
    },
    /* 获取表单动态按钮 */
    renderFormButtons (datas) {
      const _buttons = Object.values(datas)
      _buttons.map(btn => {
        if (!btn) return
        btn.validate = true
        btn.func = ({funcProps}) => {
          // if (this.dialogVisible) {
          //   // 弹窗选中下一步操作者按钮操作
          //   const _stepDefines = renderValuesForForm(funcProps.form.formValues)
          //   this.postWorkFlow(this.formValues, btn.transferType, _stepDefines)
          //   return
          // }
          this.getFormValues(funcProps, btn)
        }
      })
      return _buttons
    },
    /* 获取发起数据 */
    getFormValues ({form, button}, btn) {
      this.dialogFormValues['transType'] = btn
      this.postWorkFlow(form.formValues, btn.transferType, [], () => {
        this.formValues = form.formValues
        if (btn.turnTo && btn.openType) {
          btn.openType === 'NEWPAGE' ? setTimeout(() => {
            window.location.href = btn.turnTo
          }, 500) : this.cbDialogSlow = true
        } else {
          this.$router.go(-1)
        }
      }, button)
    },
    /**
     * @return 返回重要信息 TODO（待重要信息配置）
     */
    renderImportantInfo ({ flowValues = {}, flowColumns = {}, stepInstanceList = [] }) {
      const columnKey = keyBy(flowColumns, 'name')
      const newColumns = {
        ...defaultFlowColumns,
        ...columnKey
      }
      const {columns} = getDyncRelation({target: this, columns: newColumns}, () => {
        this.isGetInfoColumns = true
      })
      // const currentColumnKey = Object.keys(columnKey).sort((a, b) => {
      //   return columnKey[a].sort - columnKey[b].sort
      // })
      // 筛选已完结的业务节点，定义中无法获取状态，外层columns也无法
      const importantInfoList = stepInstanceList.filter(item => {
        return item.status === 'FINISH' && item.stepNature === 'BIZ'
      }).map(item => {
        const infoValues = item.formValues.reduce((obj, item) => {
          obj[item.name] = item.formValue
          return obj
        }, {})
        // console.log('item.formValues；', item.formValues)
        return {
          ...item,
          infoValues: infoValues,
          infoList: Array.from(new Set(item.formValues.filter(item => item.type !== 'subform').map(form => form.name)))
        }
      })
      this.activeName = importantInfoList[importantInfoList.length - 1].stepDefineId
      return {
        importantInfoList,
        infoColumns: columns,
        infoValues: flowValues
      }
    },
    /**
     * @params {dList} 定义步骤列表
     * @params {iList} 实例列表
     * 渲染进度条数据
     * 不显示功能节点
     * 结束-act-todo
     */
    renderStepDatas (iList, dList, stepIds) {
      let curStepIndex = 0
      const {doneList, actList, todoNode} = filterInstanceByStatus(iList, dList)
      const mixLists = actList.length ? [...doneList, actList, ...todoNode] : [...doneList, ...todoNode]
      const stepList = mixLists.map((list, index) => {
        if (isArray(list) || stepIds[list.id]) curStepIndex = index // 实例中index
        const target = isArray(list) ? list[0] : list
        return {
          index: index,
          isGroup: target.isGroup ? list : [], // 数组的显示组合
          label: target.stepDefineName || target.name,
          name: target.stepDefineId,
          type: target.stepTypeId,
          components: false,
          status: target.status || '',
          content: `${target.stepDefineName || target.name} - ${target.operatorName || ''}`
        }
      })
      // console.log('curStepIndex-', curStepIndex)
      this.stepInfoList = stepList
      if (!todoNode.length) curStepIndex = mixLists.length - 1
      this.changeStepsParams({stepList, curStepIndex})
      return {
        stepList,
        curStepIndex
      }
    },
    /* 切换step数据切换 */
    changeStepsParams ({stepList = [], curStepIndex = 0}) {
      this.curSlotName = this.stepInfoList[curStepIndex].name
      this.stepActIndex = Number(curStepIndex)
    },
    /* 返回流转路径 */
    renderTransferPath (tList = []) {
      const sourceLists = keyBy(tList, 'sourceStepDefineId')
      const sourceNodes = Object.keys(sourceLists).map(keyId => {
        const target = tList.filter(list => list.sourceStepDefineId === Number(keyId)).map(res => {
          return {
            id: res.targetStepDefineId,
            name: res.targetStepDefineName
          }
        })
        return {
          sourceId: Number(keyId),
          sourceName: sourceLists[keyId].sourceStepDefineName,
          target: target,
          transType: sourceLists[keyId].transType
        }
      })
      // console.log('sourceNode', sourceNodes)
      return sourceNodes
    },
    /**
     * @desc 发起工单审批
     */
    postWorkFlow (formValues, transType, stepDefines = [], cb = () => {}, btn = undefined) {
      this.curFormValues = formValues
      if (btn) btn.loading = true
      this.$post({
        url: `/workflow/submit/${this.flowInstanceId}/${formValues.curStepInstanceId}`,
        data: {
          stepDefines: stepDefines,
          formValues: formValues,
          transType: transType
        }
      }).then(res => {
        if (btn) btn.loading = false
        if (res.id) {
          this.dialogVisible = false
          this.$message.success('成功处理您的请求')
          this.formLists.splice(this.formLists.findIndex(list => {
            return formValues.curStepInstanceId === list.formValues.curStepInstanceId
          }), 1)
          this.$router.go(0)
          cb(res)
        } else if (res.stepDefines && res.stepDefines.length) {
          // 加弹框让用户选择id
          const {formList, columns} = renderFormByArray(res.stepDefines)
          this.dialogFormList = formList
          this.dialogColumns = columns
          this.dialogVisible = true
        } else {
          this.dialogVisible = false
        }
      })
    },
    getRelation () {
      this.isGetRelation = false
      this.$getRelation({
        relations: 'flowInstanceStatus'
      }).then((data) => {
        this.statusOptions = data.flowInstanceStatus
        this.isGetRelation = true
      }).catch(() => {
      })
    },
    /**
     * 子表操作
     * @function filterSubFormInstance 根据节点定义id筛选有子表的实例, 子表columns
     * @function getSubForm    获取
     * @function createSubForm 新增
     * @function deleteSubForm 删除
     * @function updateSubForm 编辑
     * @param {String} subName 子表对应的字段名称
     * @param {Number} formDId 子表对应的表单定义id，需要在formValues.columns中或者stepDefined中获取
     * @param {Number} flowInsId 子表对应的流程id
     *  */
    filterSubFormInstance (insStep, columns = {}) {
      const subColumns = Object.values(columns).filter(col => col.dataType === 'subform')
      const subforms = keyBy(subColumns, 'subFormId') // 所有子表, subFormId 为key，同一个子表id合为一个
      const subStepDefinedIds = Object.keys(keyBy(subColumns, 'stepDefineId'))
      const subKeys = Object.keys(subforms) // 所有子表id
      this.subColumns = subColumns // 整条流程所有子表数据
      return subKeys.map(sub => {
        return {
          ...subforms[sub],
          subStepDefinedIds: subStepDefinedIds, // 所有子表的节点定义id
          instanceId: Object.keys(keyBy(insStep.filter(step => {
            return step.stepDefineId === subforms[sub].stepDefineId
          }), 'id')) // 因为取子表数据，通过同个子表的其中一个实例Id拿全部
        }
      })
    },
    getSubForm (subName, formDId, flowInsId) {
      // 通过实例查出子表数据
      // 同个流程同个子表任意实例id可拿到该子表所有数据
      this.$get({
        url: `/workflow/subform/${formDId}/${flowInsId}`
      }).then(res => {
        if (!res.data) return []
        // 同个子表，同对象数据累加
        this.$set(this.subFormDatas, subName, Object.values(res.data))
        // 不同子表，数组加入数据 TODO 多子表
        // this.subFormDatas[subName] = Object.values(res.data)
        // console.log('this.subForm', this.subFormDatas)
        return res.data
      })
    },
    createSubForm ({data = {}, subName, formDId, flowInsId}) {
      this.$post({
        url: `/workflow/subform/${formDId}/${flowInsId}`,
        data: data
      }).then(res => {
        if (!res.id) return
        this.$message.success('新增子表记录成功')
        this.$refs.subFormStep.isShowTool = false
        // this.getSubForm(subName, formDId)
        this.$set(this.subFormDatas, subName, [
          ...this.subFormDatas[subName],
          {
            ...data,
            id: res.id
          }
        ])
        this.$refs.subFormStep.initForm()
      })
    },
    deleteSubForm ({data = {}, subName, formDId, flowInsId}) {
      // const _iId = data.stepInstanceId
      this.$httpDelete({
        url: `/workflow/subform/${formDId}/${flowInsId}/${data.id}`
      }).then(res => {
        this.$message.success('删除记录成功')
        const targetData = this.subFormDatas[subName]
        const _index = targetData.findIndex(item => item.id === data.id)
        this.$delete(this.subFormDatas[subName], _index)
        this.$refs.subFormStep.initForm()
        // console.log('targetData-after:', targetData)
      })
    },
    updateSubForm ({data = {}, subName, formDId, flowInsId}) {
      this.$patch({
        url: `/workflow/subform/${formDId}/${flowInsId}/${data.id}`,
        data: data
      }).then(res => {
        if (!res.id) return
        this.$message.success('修改记录成功')
        this.$refs.subFormStep.isShowUpdate = false
        this.getSubForm(subName, formDId, flowInsId)
      })
    },
    /**
     * 处理回退数据回填
     * 回退逻辑：当前实例的定义节点id = 之前完成的实例的定义节点id
     * @return [] 具有回退的节点列表
    */
    hadResetStep (dId) {
      const finishIList = keyBy(this.stepInstanceList.filter(list => list.status === 'FINISH'), 'stepDefineId')
      return finishIList[dId] ? finishIList[dId] : null
    }
  }
}
</script>

<style lang="sass" scoped>
.smart-form-dialogwrap
  padding: 10px
.info
  margin: 20px 30px
  background: #fff
  padding: 35px
  .number
    margin: 0 20px
    font-size: 20px
  .important-info
    border: 0
    // padding: 20px 70px 0
  .status-box
    padding: 10px
  .status
    float: right
    // margin-top: 40px
  .status-name
    float: right
    color: #48b0f7
    clear: both
    font-size: 20px
.smart-form-box
  h4
    margin: 30px 30px 0
    border-left: 4px solid #ccc
    padding-left: 10px
    box-shadow: 0px 2px 0 rgba(241,241,241,.6)
    background: #fff
  h4:active
    border-color: #47b1f6
  .smart-form-wrap
    @extend .info
    margin: 5px 30px 30px
    padding: 35px 125px
    .form-box
      width: 66%
      margin: 0 auto
    .button-wrap
      position: absoult
      margin: 30px !important
/deep/.flow-important-info
  margin-top: 5px
  border: 1px solid #ddd
  .important-wrap
    border: 0 !important
    color: #626262
  .el-collapse-item__header
    // color: #1f1c1c
    border-bottom: 1px solid #ddd
  .el-collapse-item__content
    padding-bottom: 0
    background-color: #f4f4f4
.base-title
  display: flex
  justify-content: space-around
  text-align: left
  color: #626262
  div
    width: 33.3%
.weight
  font-weight: bolder
.title-label
  background: #f6f6f6
  border-left: 5px solid #48b0f7
  padding: 0 5px
  margin-bottom: 10px
.subForm-content
  background: #fff
.col-warning
  color: red
  font-weight: 600
</style>
